﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using SharpMap.Presentation.Wpf;
using SharpMap.Rendering.Rendering2D;
using System.Diagnostics;

namespace SharpMap.Wpf
{
    public class GeoPanel : Panel
    {
  

        public static readonly DependencyProperty ToViewTransformProperty = MapControl.ToViewTransformProperty.AddOwner(typeof(GeoPanel)
      , new FrameworkPropertyMetadata(MatrixTransform.Identity
    , FrameworkPropertyMetadataOptions.Inherits
    | FrameworkPropertyMetadataOptions.AffectsArrange
    , WpfViewTransformPropertyChanged));

        public MatrixTransform ToViewTransform
        {
            get
            {
                return (MatrixTransform)GetValue(MapControl.ToViewTransformProperty);
            }
        }

        static void WpfViewTransformPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            GeoPanel This = target as GeoPanel;
        }

        //-----------------------------------------------------
        //
        //  Construction
        //
        //-----------------------------------------------------

        #region Construction
        public GeoPanel()
        {
            //Binding b = new Binding("WpfViewTransform");
            //b.Mode = BindingMode.OneWay;
            //b.Source = this;
            //SetBinding(RenderTransformProperty, b);
        }

        #endregion //Construction


        protected override void OnVisualParentChanged(DependencyObject oldParent)
        {
            base.OnVisualParentChanged(oldParent);
            DependencyObject depObj = this;
            while((depObj = VisualTreeHelper.GetParent(depObj)) != null)
            {
                MapControl mapControl = depObj as MapControl;
                if (mapControl != null)
                {
                    Binding b = new Binding("ToViewTransform");
                    b.Mode = BindingMode.OneWay;
                    b.Source = mapControl;
                    SetBinding(GeoPanel.ToViewTransformProperty, b);
                    break;
                }

            }


        }

        public static double GetWorldX(DependencyObject obj)
        {
            return (double)obj.GetValue(WorldXProperty);
        }

        public static void SetWorldX(DependencyObject obj, double value)
        {
            obj.SetValue(WorldXProperty, value);
        }


        public static readonly DependencyProperty WorldXProperty =
            DependencyProperty.RegisterAttached("WorldX", typeof(double), typeof(GeoPanel),
            new FrameworkPropertyMetadata(double.NaN, 
                WorldLocationChanged));


        static void WorldLocationChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            UIElement uie = target as UIElement;
            if (uie != null)
            {
                GeoPanel p = VisualTreeHelper.GetParent(uie) as GeoPanel;
                if (p != null)
                    p.InvalidateArrange();
            }
        }

        public static double GetWorldY(DependencyObject obj)
        {
            return (double)obj.GetValue(WorldYProperty);
        }

        public static void SetWorldY(DependencyObject obj, double value)
        {
            obj.SetValue(WorldYProperty, value);
        }

        public static readonly DependencyProperty WorldYProperty =
            DependencyProperty.RegisterAttached("WorldY", typeof(double), typeof(GeoPanel),
            new FrameworkPropertyMetadata(double.NaN, 
                WorldLocationChanged));

        #region view coords
 
        #endregion

        protected override Size MeasureOverride(Size availableSize)
        {
            foreach (UIElement e in InternalChildren)
            {
                e.Measure(availableSize);
            }
            return availableSize;
        }

        protected override Size ArrangeOverride(Size arrangeSize)
        {
            Rect finalRect = new Rect(0, 0, 0, 0);
             foreach (UIElement e in InternalChildren)
            {
                Rect r = new Rect(e.DesiredSize);
                Point location ;
                double wx = GetWorldX(e);
                 double wy = GetWorldY(e);
                 if (!double.IsNaN(wx) && !double.IsNaN(wy))
                 {
                     location = ToViewTransform.Transform(new Point(wx, wy));
                     //move center to desired location, instead of upper left
                     location.Offset(-e.DesiredSize.Width / 2.0, -e.DesiredSize.Height / 2.0);
                     r.Location = location;
                 }
                 else
                 {
                     e.RenderTransform = ToViewTransform;
                 }
                 e.Arrange(r);
                finalRect.Union(r);
            }
            return arrangeSize;

        }
    }
}
